﻿#include "stdafx.h"
#include "StateMove.h"
#include "FSM.h"
#include "LifeObject.h"

StateMove::StateMove(FSM *fsm, LifeObject *obj) : FSMState(fsm)
{
	m_object = obj;
	m_stateName = "move";
	m_stateType = FSM::st_move;
}


StateMove::~StateMove()
{
}

bool StateMove::Enter()
{
	if (MakePath(m_fsm->m_move.pt))
	{
		m_object->m_animate.DisabledLastFrame(true);
		m_object->m_animate.m_cb_enterFrame = std::bind(&StateMove::cb_enterFrame, this, _1);
		int currAnim = m_object->m_animate.GetCurrAnimIndex();
		int index_move = m_object->GetAnimIndex_move();
		if (currAnim != index_move)
		{
			m_object->m_animate.SetAnimation(index_move);
		}
		m_preFrameOffset = m_firstFrameOffset = m_object->m_animate.GetFirstFrameRootNodePosition().y;
		m_object->m_animPosOffset = 0.0f;
		m_moveCount = 0;
		return true;
	}
	else
	{
		m_fsm->ChangeToNextState();
		return false;
	}
}

void StateMove::CalcStepLength()
{
	m_stepLength = (m_object->m_mapDir & 1 ? 100.f : 141.42f);
}

bool StateMove::MakePath(POINT &dest)
{
	m_endPoint = dest;
	auto &start = m_object->GetMapPos();
	if (m_object->MakePath(start, m_endPoint, m_movePath))
	{
		m_movePath.pop_front();
		m_nextPoint = m_movePath.front();
		m_object->SetDir(m_nextPoint);
		CalcStepLength();
		return true;
	}
	return false;
}

void StateMove::Run()
{
	glm::mat4 *mats = nullptr;
	int numMats = m_object->m_animate.GetBoneTransformMatrixs(&mats);
	float off = mats[0][3].y;
	float step = m_preFrameOffset - off;
	m_preFrameOffset = off;
	m_object->m_animPosOffset += step;
	m_moveCount += step;
	if (m_moveCount >= m_stepLength)
	{
		m_moveCount -= m_stepLength;
		auto pt1 = m_nextPoint;
		m_object->SetMapPos(pt1);
		m_object->SetPosition(pt1.x * 100 + 50, pt1.y * 100 + 50);
		m_movePath.pop_front();
		if (m_cb_position && m_cb_position(pt1))
		{
			//m_object->SetPosition(pt1.x * 100 + 50, pt1.y * 100 + 50);
			return;
		}
		if (m_movePath.empty())
		{
			//走完退出
			//m_object->CalcMapPosition(pt1);
			m_object->SetPosition(pt1.x * 100 + 50, pt1.y * 100 + 50);
			Exit();
			//m_object->SetDir(m_fsm->m_move.dirIdx);
			m_fsm->ChangeToNextState();
		}
		else
		{
			//有可能已经超过了目标位置，插值在新位置和下一步之间进行
			m_nextPoint = m_movePath.front();
			m_object->SetDir(m_nextPoint);
			CalcStepLength();
			auto pos3 = glm::mix(glm::vec2(pt1.x, pt1.y), glm::vec2(m_nextPoint.x, m_nextPoint.y), m_moveCount / m_stepLength);
			m_object->SetPosition(pos3.x * 100.0f + 50.0f, pos3.y * 100.0f + 50.0f);
		}
	}
	else
	{
		//在两步之间插值产生平滑的移动位置
		auto &pt1 = m_object->GetMapPos();
		auto pos3 = glm::mix(glm::vec2(pt1.x, pt1.y), glm::vec2(m_nextPoint.x, m_nextPoint.y), m_moveCount / m_stepLength);
		m_object->SetPosition(pos3.x * 100.0f + 50.0f, pos3.y * 100.0f + 50.0f);
	}
}

void StateMove::Exit()
{
	m_object->m_requestMove = false;
	m_object->m_animate.DisabledLastFrame(false);
	m_object->m_animate.m_cb_enterFrame = nullptr;
}

void StateMove::cb_enterFrame(int index)
{
	switch (index)
	{
	case 0:
		m_object->m_animPosOffset = 0.0f;
		m_preFrameOffset = m_firstFrameOffset;
		break;
	case 3:
	case 6:
		m_object->PlayWalkSound();
		break;
	default:
		break;
	}
}

void StateMove::Pause()
{
	m_object->m_animate.Pause();
}

bool StateMove::Continue()
{
	m_object->m_animate.Continue();
	return true;
}